﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.SweptVolume.CApSVSweptVolume
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using System;
using System.Collections.ObjectModel;
using System.Resources;
using System.Windows.Forms;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.SweptVolume;

public class CApSVSweptVolume
{
  private const double minimalSVTimeInterval = 0.05;
  private const short BEFORE_SAMPLING = 0;
  private const short SAMPLING_STARTED = 1;
  private const short GRAPHIC_CALCULATION_STARTED = 2;
  private const double SWEPT_VOLUME_TRANSPARENCY_LEVEL = 0.7;
  protected ITxSweptVolumeHoldingObject m_svhObject;
  protected CApSVSweptVolumeCreationSamplingManager m_samplingManager;
  private TxSweptVolume_MayProceedCalculation m_mayProceedCallback;
  private double m_accuracy;
  private double m_clearance;
  private short m_stage;
  private bool m_shouldAbort;
  private bool m_rewind;
  private TxObjectList<ITxDisplayableObject> m_blankedObjsBeforeCalculate = new TxObjectList<ITxDisplayableObject>(0);

  internal event CApSimulationHandler_SimulationInitializedEventHandler SimulationInitialized;

  public TxSweptVolume_MayProceedCalculation CallBack
  {
    set => this.m_mayProceedCallback = value;
  }

  public bool Rewind
  {
    get => this.m_rewind;
    set => this.m_rewind = value;
  }

  public ITxSweptVolumeHoldingObject SVHoldingObject => this.m_svhObject;

  public CApSVSweptVolume(ITxSweptVolumeHoldingObject svhObject)
  {
    this.m_svhObject = svhObject;
    // ISSUE: method pointer
    this.m_mayProceedCallback = new TxSweptVolume_MayProceedCalculation((object) this, __methodptr(mayProceed));
    this.m_shouldAbort = false;
    this.m_stage = (short) 0;
    this.m_rewind = true;
  }

  public void createSweptVolume(double accuracy, double clearance, bool includeCables)
  {
    TxApplication.ActiveUndoManager.ClearAllTransactions();
    this.m_accuracy = accuracy;
    this.m_clearance = clearance;
    this.initSamplingManager(includeCables);
    this.m_stage = (short) 1;
    this.m_samplingManager.startSampling();
    this.onSamplingEnded();
  }

  public void abort()
  {
    this.m_shouldAbort = true;
    if (this.m_stage != (short) 1)
      return;
    this.m_samplingManager.stopSampling();
  }

  protected virtual void initSamplingManager(bool includeCables)
  {
    double timeInterval = TxApplication.Options.Motion.TimeInterval;
    if (0.05 < timeInterval)
      timeInterval = 0.05;
    CApSVTimeSampleSimulationHandler simHandler;
    if (this.m_svhObject is ITxOrderedCompoundOperation)
      simHandler = new CApSVTimeSampleSimulationHandler(this.m_svhObject as ITxOrderedCompoundOperation, timeInterval);
    else
      simHandler = this.m_svhObject is ITxRoboticProgram ? new CApSVTimeSampleSimulationHandler(this.m_svhObject as ITxRoboticProgram, timeInterval) : throw new InvalidOperationException("Unsupported simulation object: " + this.m_svhObject.ToString());
    simHandler.RefreshDisplay = false;
    CApSVSamplingObjectsHandler objHandler = new CApSVSamplingObjectsHandler((ITxObject) (CApSVUtilities.getRootObject(this.m_svhObject) ?? throw new NullReferenceException("CApSVSweptVolume: createSweptVolume: operation does not have a root object")), includeCables);
    this.m_samplingManager = new CApSVSweptVolumeCreationSamplingManager(simHandler, objHandler, includeCables);
    this.m_samplingManager.CallBack = this.m_mayProceedCallback;
    this.m_samplingManager.Rewind = this.Rewind;
    this.m_samplingManager.SimulationHandler.SimulationInitialized += new CApSimulationHandler_SimulationInitializedEventHandler(this.m_samplingManager_SimulationInitialized);
  }

  protected virtual void onSamplingEnded()
  {
    if (!this.m_shouldAbort && this.m_samplingManager.SweptVolumeCalculationData.ObjectsData.Length == 0 && this.m_samplingManager.SweptVolumeCalculationData.CablesData.Length == 0 && !this.canCreateEmptySweptVolume())
      this.m_shouldAbort = true;
    if (this.m_shouldAbort)
      return;
    this.completeSweptVolumeCreation();
  }

  protected virtual bool canCreateEmptySweptVolume()
  {
    string str1 = string.Empty;
    if (((Collection<ITxObject>) this.m_svhObject.SweptVolumes).Count > 0)
      str1 = ((Collection<ITxObject>) this.m_svhObject.SweptVolumes)[0].Name;
    ResourceManager resourceManager = new ResourceManager("DnProcessSimulateCommands.SweptVolume.StringTable", this.GetType().Assembly);
    string str2 = resourceManager.GetString("SV_NAME");
    return TxMessageBox.Show(string.IsNullOrEmpty(str1) ? resourceManager.GetString("SV_CONFIRM_NEW_EMPTY_SWEPT_VOLUME") : string.Format(resourceManager.GetString("SV_CONFIRM_EMPTY_SWEPT_VOLUME"), (object) str1), str2, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
  }

  protected virtual string generateSweptVolumeObjectName(
    ITxSweptVolumeHoldingObject svhObject,
    double accuracy,
    double clearance)
  {
    string name = ((ITxObject) this.m_svhObject).Name;
    string linearUnitName = TxApplication.Options.Units.LinearUnitName;
    double linearMultiplier = TxApplication.Options.Units.LinearMultiplier;
    ResourceManager resourceManager = new ResourceManager("DnProcessSimulateCommands.SweptVolume.StringTable", this.GetType().Assembly);
    string str1 = "{0:f";
    string format = linearMultiplier != 1.0 ? $"{str1}{TxApplication.Options.Units.LinearDigitsAfterDecimalPoint.ToString()}}}" : str1 + "0}";
    double num1 = accuracy / linearMultiplier;
    string str2 = $"{name}_{string.Format(format, (object) num1)}{linearUnitName}";
    if (clearance > 0.0)
    {
      double num2 = clearance / linearMultiplier;
      str2 = $"{$"{str2}_{resourceManager.GetString("SV_CLEARANCE")}"}_{string.Format(format, (object) num2)}{linearUnitName}";
    }
    return TxApplication.ActiveDocument.PhysicalRoot.GetUniqueDisplayName($"{str2}_{resourceManager.GetString("SV_VOLUME")}");
  }

  protected virtual void setDisplayMode(TxSweptVolume sweptVolume)
  {
    try
    {
      sweptVolume.Color = new TxColor(sweptVolume.Color)
      {
        Transparency = 0.7
      };
    }
    catch (Exception ex)
    {
    }
  }

  private void completeSweptVolumeCreation()
  {
    TxObjectList sweptVolumes = this.m_svhObject.SweptVolumes;
    TxSweptVolume withClearanceType = CApSVSweptVolume.getSVWithClearanceType(this.m_svhObject, this.m_clearance);
    if (TxSweptVolume.op_Inequality((TxSweptVolume) null, (ITxObject) withClearanceType))
      this.updateSweptVolume(withClearanceType);
    else
      this.createNewSweptVolume();
  }

  private void createNewSweptVolume()
  {
    TxApplication.ActiveUndoManager.ClearAllTransactions();
    TxSweptVolume sweptVolume = this.m_svhObject.CreateSweptVolume(new TxSweptVolumeCreationData());
    sweptVolume.Accuracy = this.m_accuracy;
    sweptVolume.Clearance = this.m_clearance;
    sweptVolume.Name = this.generateSweptVolumeObjectName(this.m_svhObject, this.m_accuracy, this.m_clearance);
    TxSweptVolumeCalculationData volumeCalculationData = this.m_samplingManager.SweptVolumeCalculationData;
    this.m_stage = (short) 2;
    this.beforeCalculateSweptVolume(this.m_samplingManager.SweptVolumeCalculationData);
    try
    {
      sweptVolume.Calculate(volumeCalculationData, this.m_mayProceedCallback);
    }
    catch (TxSweptVolumeCalculationFailedException ex)
    {
      this.afterCalculateSweptVolume();
      sweptVolume.Delete();
      throw ex;
    }
    this.afterCalculateSweptVolume();
    if (this.m_shouldAbort)
    {
      sweptVolume.Delete();
    }
    else
    {
      sweptVolume.Lock();
      this.setDisplayMode(sweptVolume);
    }
    TxApplication.ActiveUndoManager.ClearAllTransactions();
  }

  private void updateSweptVolume(TxSweptVolume sv)
  {
    TxApplication.ActiveUndoManager.ClearAllTransactions();
    double accuracy = sv.Accuracy;
    double clearance = sv.Clearance;
    string name = sv.Name;
    TxSweptVolumeCalculationData volumeCalculationData = this.m_samplingManager.SweptVolumeCalculationData;
    this.m_stage = (short) 2;
    TxColor txColor = (TxColor) null;
    try
    {
      txColor = sv.Color;
    }
    catch (Exception ex)
    {
    }
    sv.Unlock();
    sv.Accuracy = this.m_accuracy;
    sv.Clearance = this.m_clearance;
    sv.Name = this.generateSweptVolumeObjectName(this.m_svhObject, this.m_accuracy, this.m_clearance);
    sv.Clear();
    TxApplication.ActiveUndoManager.ClearAllTransactions();
    this.beforeCalculateSweptVolume(this.m_samplingManager.SweptVolumeCalculationData);
    try
    {
      sv.Calculate(volumeCalculationData, this.m_mayProceedCallback);
    }
    catch (TxSweptVolumeCalculationFailedException ex)
    {
      this.afterCalculateSweptVolume();
      sv.Rollback();
      sv.Accuracy = accuracy;
      sv.Clearance = clearance;
      sv.Name = name;
      if (TxColor.op_Inequality(txColor, (TxColor) null))
        sv.Color = txColor;
      throw ex;
    }
    this.afterCalculateSweptVolume();
    if (this.m_shouldAbort)
    {
      sv.Rollback();
      sv.Accuracy = accuracy;
      sv.Clearance = clearance;
      sv.Name = name;
      sv.Color = txColor;
    }
    else
    {
      if (sv.Name.Contains(name))
        sv.Name = this.generateSweptVolumeObjectName(this.m_svhObject, this.m_accuracy, this.m_clearance);
      sv.Lock();
    }
    TxApplication.ActiveUndoManager.ClearAllTransactions();
  }

  private bool mayProceed(int i) => true;

  internal static TxSweptVolume getSVWithClearanceType(
    ITxSweptVolumeHoldingObject svhObj,
    double clearance)
  {
    TxSweptVolume withClearanceType = (TxSweptVolume) null;
    foreach (TxSweptVolume sweptVolume in (Collection<ITxObject>) svhObj.SweptVolumes)
    {
      if (TxSweptVolume.op_Equality((TxSweptVolume) null, (ITxObject) withClearanceType))
      {
        if (sweptVolume.Clearance + clearance == 0.0)
          withClearanceType = sweptVolume;
        else if (sweptVolume.Clearance * clearance != 0.0)
          withClearanceType = sweptVolume;
      }
    }
    return withClearanceType;
  }

  private void m_samplingManager_SimulationInitialized(object sender, EventArgs e)
  {
    if (this.SimulationInitialized == null)
      return;
    this.SimulationInitialized(sender, e);
  }

  private void beforeCalculateSweptVolume(TxSweptVolumeCalculationData calcData)
  {
    TxObjectSweptVolumeCalculationData[] objectsData = calcData.ObjectsData;
    int length = objectsData != null ? objectsData.GetLength(0) : 0;
    this.m_blankedObjsBeforeCalculate = new TxObjectList<ITxDisplayableObject>(length);
    if (length > 0 && objectsData != null)
    {
      for (int index = 0; index < length; ++index)
      {
        if (objectsData[index].Object is ITxDisplayableObject displayableObject && displayableObject.Visibility == 2)
          ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Add(displayableObject);
      }
    }
    int count = ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Count;
    if (count <= 0)
      return;
    for (int index = 0; index < count; ++index)
    {
      try
      {
        ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate)[index].Display();
      }
      catch
      {
      }
    }
  }

  private void afterCalculateSweptVolume()
  {
    int count = ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Count;
    for (int index = 0; index < count; ++index)
    {
      try
      {
        ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate)[index].Blank();
      }
      catch
      {
      }
    }
    ((Collection<ITxDisplayableObject>) this.m_blankedObjsBeforeCalculate).Clear();
  }
}
